﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Pampa.CRUD.Configuration;
using Pampa.CRUD.Core;
using Pampa.CRUD.Security;
using Pampa.MVC.Fluent.Common;
using Pampa.MVC.Fluent.Crud.Groups;
using Pampa.MVC.Security;

namespace Pampa.MVC.Fluent.Crud
{
    public abstract class EntityConfig : AbstractBuilder
    {
        protected ISecurityManager _securityManager;

        protected EntityConfig()
        {
            this.Configuration = new EntityConfiguration();
        }

        public abstract void Init();

        internal EntityConfiguration Configuration
        {
            get; 
            set;
        }

        internal ISecurityManager SecurityManager
        {
            get { return _securityManager; }
        }
    }

    public abstract class EntityConfig<TEditor> : EntityConfig
    {
        protected EntityConfig() : base()
        {
            _securityManager = new SecurityManagerRules<TEditor>();
        }

        internal new SecurityManagerRules<TEditor> SecurityManager
        {
            get { return (SecurityManagerRules<TEditor>)_securityManager; }
        }

        protected HeaderGroupBuilder<TEditor> AddGroup()
        {
            var group = new HeaderGroup();
            group.Id = "Group" + this.Configuration.Groups.Count;

            this.Configuration.Groups.Add(group);

            return new HeaderGroupBuilder<TEditor>(this, group);
        }

        protected DetailsGroupBuilder<TGroup, TEditor> AddListGroup<TGroup>(Expression<Func<TEditor, IList<TGroup>>> property)
        {
            var group = new DetailsGroup();
            group.Id = GetId(property);
            group.TypeName = typeof(TGroup).AssemblyQualifiedName;

            this.Configuration.Groups.Add(group);

            return new DetailsGroupBuilder<TGroup, TEditor>(this, group);
        }

        protected DetailsGroupBuilder<TGroup, TEditor> AddListGroup<TGroup>(Expression<Func<TEditor, dynamic>> property)
        {
            var group = new DetailsGroup();
            group.Id = GetId(property);
            group.TypeName = typeof(TGroup).AssemblyQualifiedName;

            this.Configuration.Groups.Add(group);

            return new DetailsGroupBuilder<TGroup, TEditor>(this, group);
        }

        /// <summary>
        /// Allows to override save action.
        /// Action returns true if the entity repository save action should be called after this.
        /// This is also usefull for validating before save.
        /// </summary>
        protected void OnSave(Expression<Func<TEditor, bool>> action)
        {
            EntityManager.OnSave(action);
        }
    }
}
